/*
 ============================================================================
 Name		: RCallStack.h
 Author	  : wangli@opi-corp.com
 Version	 : 1.0
 Copyright   : Your copyright notice
 Description : RCallStack declaration
 ============================================================================
 */

#ifndef RCALLSTACK_H
#define RCALLSTACK_H

// INCLUDES
#include <e32std.h>
#include <e32base.h>

#include "Service.h"

class TItem;

/**
 *  RCallStack: Global Stack for Client and Server
 *  @Invariant 
 *      if Count()==0 then isEmpty()==ETrue; 
 */
class RCallStack
{
public:
   RCallStack();
   ~RCallStack();
   
   /**
    * @pre aSize > 0;
    * @pre aStackName.length > 0 && aStackName <= KMaxFullName
    * @Post TFindChunk.Next(aStackName) == KErrNone;
    *       IsAvaliable() == true;
    *       isEmpty() == true;
    *       Count() == 0;
    */
   void CreateL(const TDesC& aStackName, TInt aSize);
   
   /**
    * @pre aStackName.length > 0 && aStackName <= KMaxFullName
    * @post IsAvaliable() == ETrue;
    */
   void OpenL(const TDesC& aStackName);
   void Close();
   
   /**
    * @pre aItem.Size() > 0
    * @post aItem.Equal(Top()) == true;
    */
   void Push(const TItem& aItem);
   
   /**
    * @pre aSize > 0;
    *      aObject != NULL;
    * @post 
    *      Top().Type() == aType;
    *      Top().Size() == sizeof(TItem) + aSize;
    */
   void Push(EItemType aType, TUint16 aSize, const TAny* aObject);
   
   void Pop();
   /**
    * @result
    *   栈顶元素的引用
    * 如果栈是空的,则会引发RCallStack 2的Panic 
    */
   const TItem& Top()const;
   
   inline TBool isEmpty()const
   {
       return ( *getSp() ==0 );
   }
   
   inline TBool IsAvaliable()const
   {
       return (iChunkBottom != NULL);
   }
   
   /**
    * @result
    *      获取栈中元素的个数
    */
   inline TUint Count()const
   {
       return *getCount();
   }
   
   /**
    * @result 栈的大小
    */
   inline TUint Size()const
   {
       return  iChunkTop - iChunkBottom;
   }
   
   /**
    * 将整个栈的内容转换为描述符
    *   TODO:设置为迭代器的形式，可依次访问栈中的所有元素
    */
   TDesC* DumpL()const;
 
private:
   inline TUint8* getTop()const
   {
       return iChunkTop - *((TUint*)iChunkBottom);
   }
   
   inline TUint* getSp()const
   {
       return (TUint*)iChunkBottom;
   }
   
   inline TUint* getCount()const
   {
       return (TUint*)(iChunkBottom + sizeof(TUint));
   }
   
   void checkFreeSize(TUint aSize)const;
   
private:
   RChunk iStackChunk;
   TUint8* iChunkTop;
   TUint8* iChunkBottom;
};

#endif // RCALLSTACK_H
